﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Dpx.Models;
using SQLite;

namespace Dpx.Services {
    /// <summary>
    /// 收藏存储。
    /// </summary>
    public class FavoriteStorage : IFavoriteStorage {
        /******** 公开变量 ********/

        /// <summary>
        /// 数据库名。
        /// </summary>
        public const string DbName = "favoritedb.sqlite3";


        /******** 私有变量 ********/

        /// <summary>
        /// 偏好存储。
        /// </summary>
        private IPreferenceStorage _preferenceStorage;

        /// <summary>
        /// 收藏数据库路径。
        /// </summary>
        private static readonly string PoetryDbPath =
            Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder
                    .LocalApplicationData), DbName);

        /// <summary>
        /// 数据库连接影子变量。
        /// </summary>
        private SQLiteAsyncConnection _connection;

        /// <summary>
        /// 数据库连接。
        /// </summary>
        private SQLiteAsyncConnection Connection =>
            _connection ??= new SQLiteAsyncConnection(PoetryDbPath);

        /******** 继承方法 ********/

        /// <summary>
        /// 是否已经初始化。
        /// </summary>
        public bool Initialized() =>
            _preferenceStorage.Get(FavoriteStorageConstants.VersionKey, -1) ==
            FavoriteStorageConstants.Version;

        /// <summary>
        /// 初始化。
        /// </summary>
        public async Task InitializeAsync() {
            await Connection.CreateTableAsync<Favorite>();
            _preferenceStorage.Set(FavoriteStorageConstants.VersionKey,
                FavoriteStorageConstants.Version);
        }

        /// <summary>
        /// 获取一个收藏 。
        /// </summary>
        /// <param name="poetryId">诗词id。</param>
        public async Task<Favorite> GetFavoriteAsync(int poetryId) =>
            await Connection.Table<Favorite>()
                .FirstOrDefaultAsync(p => p.PoetryId == poetryId);

        /// <summary>
        /// 获得所有收藏。
        /// </summary>
        public async Task<IList<Favorite>> GetFavoritesAsync() =>
            await Connection.Table<Favorite>().Where(p => p.IsFavorite)
                .ToListAsync();

        /// <summary>
        /// 保存收藏。
        /// </summary>
        /// <param name="favorite">待保存的收藏。</param>
        /// <param name="generateTimestamp">是否生成时间戳。</param>
        public async Task SaveFavoriteAsync(Favorite favorite, bool generateTimestamp) {
            if (generateTimestamp) {
                favorite.Timestamp = DateTime.Now.Ticks;
            }

            await Connection.InsertOrReplaceAsync(favorite);
            Updated?.Invoke(this,
                new FavoriteStorageUpdatedEventArgs(favorite));
        }

        /// <summary>
        /// 所获得所有收藏项，包括收藏与非收藏。
        /// </summary>
        public async Task<IList<Favorite>> GetFavoriteItemsAsync() =>
            await Connection.Table<Favorite>().ToListAsync();

        /// <summary>
        /// 收藏已更新
        /// </summary>
        public event EventHandler<FavoriteStorageUpdatedEventArgs> Updated;

        /******** 公开方法 ********/

        /// <summary>
        /// 收藏存储。
        /// </summary>
        /// <param name="preferenceStorage">偏好存储。</param>
        public FavoriteStorage(IPreferenceStorage preferenceStorage) {
            _preferenceStorage = preferenceStorage;
        }

        /// <summary>
        /// 关闭数据库。
        /// </summary>
        public async Task CloseAsync() => await Connection.CloseAsync();

        /******** 私有方法 ********/
    }

    /// <summary>
    /// 收藏存储常量。
    /// </summary>
    public static class FavoriteStorageConstants {
        /// <summary>
        /// 版本。
        /// </summary>
        public const string VersionKey =
            nameof(IFavoriteStorage) + "." + nameof(Version);

        /// <summary>
        /// 版本。
        /// </summary>
        public const int Version = 1;
    }
}